<template>
  <div class="executor-main">
    <el-container id="old-history" direction="vertical" />
    <el-container id="new-history" direction="vertical">
      <!-- 应用启动信息 -->
      <el-container direction="vertical">
        <el-main class="args user">
          <img :src="require(`@/assets/avatars/${avatarIndex}.jpg`)" alt="User" class="user-avatar">
          <div id="start-app-dialog" class="content-wrapper dialog-box">
            <strong class="bold-text">{{ $t('launch') }}{{ $t('application') }}：</strong>{{ this.appName }}
          </div>
        </el-main>
      </el-container>

      <!-- 循环展示每一步任务的用户输入和执行结果 -->
      <div v-for="(step, index) in executionSteps" :key="index">
        <!-- 用户输入 -->
        <el-container v-if="index === displayNowOnTask && !step.canceled">
          <el-main v-if="hasInputArgs(step)">
            <!--          <el-main>-->
            <div style="overflow: hidden;">
              <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">
            </div>
            <div style="clear: both;" />
            <div>
              <div v-if="step.prompt" class="content-wrapper dialog-box">
                {{ step.prompt }}
              </div>
              <el-form class="content-wrapper dialog-box" @submit.native.prevent="submitForm">
                <div v-for="(arg, argIndex) in step.userInput" :key="argIndex">
                  <div v-if="arg.source === 'input'">
                    <template v-if="arg.input.options">
                      <template v-if="isSingleChoice(arg.input.options)">
                        <el-form-item :label="arg.input.prompt">
                          <br>
                          <div v-for="(option, optionIndex) in arg.input.options" :key="optionIndex">
                            <el-radio v-model="arg.value" :label="option.value">{{ option.name }}</el-radio>
                          </div>
                        </el-form-item>
                      </template>
                      <template v-else>
                        <el-form-item :label="arg.input.prompt">
                          <br>
                          <div v-for="(option, optionIndex) in arg.input.options" :key="optionIndex">
                            <el-checkbox v-model="arg.value" :label="option.value">{{ option.name }}</el-checkbox>
                          </div>
                        </el-form-item>
                      </template>
                    </template>
                    <template v-else>
                      <el-form-item :label="arg.input.prompt">
                        <el-input
                          v-if="arg.input.inputMode === 'singleLine'"
                          v-model="arg.value"
                          v-focus="argIndex === 0"
                          @keyup.enter="submitForm"
                        />
                        <el-input
                          v-if="arg.input.inputMode === 'mulitiLine'"
                          v-model="arg.value"
                          v-focus="argIndex === 0"
                          type="textarea"
                          @keyup.enter="submitForm"
                        />
                      </el-form-item>
                    </template>
                  </div>
                  <div v-else-if="arg.source === 'file'">
                    <el-form-item>
                      <el-upload
                        :http-request="uploadFile"
                        :before-remove="beforeRemoveFile"
                        drag
                        :limit="1"
                        :on-exceed="handleExceed"
                        :first-list="fileList"
                        style="margin-top: 15px"
                      >
                        <i class="el-icon-upload" />
                        <div class="el-upload__text">{{ $t('Drag_file_tips') }}<em>{{ $t('click') + $t('upload') }}</em>
                        </div>
                      </el-upload>
                    </el-form-item>
                  </div>
                </div>
                <el-form-item style="text-align: center">
                  <el-button type="primary" @click="submitForm">{{ $t('submit') }}</el-button>
                  <el-button @click="cancelExecution(index)">{{ $t('cancel') }}</el-button>
                </el-form-item>
              </el-form>
            </div>
          </el-main>
          <el-main v-if="step.canceled">
            <div style="overflow: hidden;">
              <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">
            </div>
            <div style="clear: both;" />
            <div class="content-wrapper dialog-box">
              {{ $t('user_terminated_execution_tip') }}
            </div>
          </el-main>
        </el-container>

        <!--        <div id="image_load" />-->
        <!-- 用户输入的展示 -->
        <el-container v-if="index < displayNowOnTask">
          <el-main v-check-empty>
            <div>
              <div v-if="hasInputParam(step.userInput)">
                <!--                  元芳右面的图标   +提示词-->
                <!--                  <div style="overflow: hidden;">-->
                <!--                    <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">-->
                <!--                  </div>-->
                <!--                  <div class="content-wrapper dialog-box">{{ arg.input.prompt }}</div><br>-->
                <!--                  <div />-->
                <!--                  元芳左面的图标 +用户回答-->
                <img
                  :src="require(`@/assets/avatars/${avatarIndex}.jpg`)"
                  alt="User"
                  class="user-avatar"
                ><br>
                <!--                  <div class="content-wrapper dialog-box">{{ allUserInputs[index][arg.name] }}</div><br>-->
                <!--                  <div />-->
                <div class="content-wrapper dialog-box">
                  <div v-for="(arg, argIndex) in step.userInput" v-if="arg.source === 'input'" :key="argIndex">
                    {{ arg.input.prompt }}：{{ allUserInputs[index][arg.name] }}
                  </div>
                </div><br>
                <div />
              </div>
              <div v-for="(arg, argIndex) in step.userInput" v-if="arg.source === 'file'" :key="argIndex">
                <div>
                  <div style="overflow: hidden;">
                    <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">
                  </div>
                  <div class="content-wrapper dialog-box">{{ $t('upload_file') }}</div><br>
                  <div />
                  <img
                    :src="require(`@/assets/avatars/${avatarIndex}.jpg`)"
                    alt="User"
                    class="user-avatar"
                  ><br>

                  <div class="content-wrapper dialog-box">
                    <img :src="getOringalImg()" alt="Uploaded Image" style="maxWidth: 100%;" class="responsive-image">
                    <br>
                    已上传成功
                    <a :href="downloadUrl()" :download="file.name" class="download-link">下载</a>
                  </div><br>
                  <div />
                </div>
              </div>
            </div>
          </el-main>
        </el-container>

        <!-- 执行结果 -->
        <!--        <el-container v-if="index < nowOnTask ">-->
        <el-container v-if="index < nowOnTask">
          <!--          <el-container v-if="index < nowOnTask && displayedResultsNum === 0">-->
          <el-main :style="displayedResultsNum[index] !== 1 ? 'display: none;' : 'display: block;' ">
            <div v-if="displayedResultsNum[index] === 1" style="overflow: hidden;">
              <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">
            </div>
            <div style="clear: both;" />
            <template v-if="executeLogs[index]">
              <div :id="`chart-${index}`" style="display: none;height: 500px;" class="content-wrapper dialog-box" />
              <div :id="`text-${index}`" style="display: none;" class="content-wrapper dialog-box" />
              <div :id="`file-${index}`" style="display: none;" class="content-wrapper dialog-box" />
            </template>
          </el-main>
        </el-container>

        <!--&lt;!&ndash;        &lt;!&ndash; 执行结果 &ndash;&gt;&ndash;&gt;-->
        <!--        <el-container v-if="index < (displayedResultsNum > 0 ? displayedResultsNum : nowOnTask) && displayedResultsNum > 0">-->
        <!--          <el-main>-->
        <!--            <div style="overflow: hidden;">-->
        <!--              <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">-->
        <!--            </div>-->
        <!--            <div style="clear: both;" />-->
        <!--            <template v-if="executeLogs[index]">-->
        <!--              <div :id="`chart-${index}`" style=" height: 500px;" class="content-wrapper" />-->
        <!--              <div :id="`text-${nowOnTask - 1}`" style="display: none;" class="content-wrapper" />-->
        <!--              <div :id="`file-${nowOnTask - 1}`" style="display: none;" class="content-wrapper" />-->
        <!--            </template>-->
        <!--          </el-main>-->
        <!--        </el-container>-->

        <!-- <div :id="`chart-${index}`" style=" height: 500px;" class="content-wrapper"></div> -->
      </div>

      <el-container v-if="waitingTaskList && !errorMessage && !executionCompleted">
        <el-main>
          <div class="content-wrapper dialog-box">
            <div
              v-loading="waitingTaskList"
              :element-loading-text="$t('appThinking')"
              element-loading-spinner="el-icon-loading"

              style="border-radius: 10px; padding: 10px; height: 40px"
            />
          </div>

          <!--          <div  class="content-wrapper dialog-box" />-->
        </el-main>
      </el-container>

      <!-- 错误消息展示 -->
      <el-container v-if="errorMessage">
        <el-main>
          <div style="overflow: hidden;">
            <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">
          </div>
          <div style="clear: both;" />
          <div class="content-wrapper dialog-box">
            哎呀，看起来元芳遇到了个小坎坷！
            <a @click="toggleErrorLog">[错误日志]</a>
            <div v-if="showErrorLog">{{ errorMessage }}
            </div>
          </div>
          <div class="button-container">
            <el-button @click="restartExecution">{{ $t('re_run') }}</el-button>
          </div>
        </el-main>
      </el-container>

      <!-- 任务执行完毕后显示元芳图标和“已运行完毕！” -->
      <el-container v-if="executionCompleted">
        <el-main>
          <div style="overflow: hidden;">
            <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">
          </div>
          <div style="clear: both;" />
          <div ref="completionMessage" class="content-wrapper dialog-box">
            “{{ this.appName }}”{{ $t('finished_running') }}
          </div>
          <div id="re-start" class="button-container">
            <el-button @click="restartExecution">{{ $t('re_run') }}</el-button>
          </div>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
import { getAppDetail, executeAppStep, getExecutroMemoryBus, processOutput } from '@/api/executor'
import jsonEdit from '@/components/AppCreate/task/jsonEdit.vue'
import outputEdit from '@/components/AppCreate/output/outputEdit.vue'
import * as echarts from 'echarts'
import { uploadFile, downloadFile } from '@/api/executor'
import { getProfileById } from '@/api/profile'

export default {
  components: { jsonEdit, outputEdit },
  // 注册指令check-empty，检查内容是否为空，如果为空，就让他消失
  directives: {
    'check-empty': {
      inserted(el) {
        // 查找子元素中的 div 标签
        const divElement = el.querySelector('div')

        // 判断 div 的内容是否为 `<!----><!---->`
        if (divElement && divElement.innerHTML.trim() === '<!----><!---->') {
          el.style.display = 'none' // 隐藏父元素
        }
      },
      update(el) {
        // 查找子元素中的 div 标签
        const divElement = el.querySelector('div')

        // 判断 div 的内容是否为 `<!----><!---->`
        if (divElement && divElement.innerHTML.trim() === '<!----><!---->') {
          el.style.display = 'none' // 隐藏父元素
        } else {
          el.style.display = 'block' // 显示父元素
        }
      }
    }
  },
  data() {
    return {
      memoryBusData: {}, // 用来存储不同 taskNum 对应的 memoryBus 数据
      imageId: 0, // 图片ID，初始值为0
      appDetail: {},
      appName: '',
      nowOnTask: 0,
      nowTaskContent: {},
      nowTaskArgs: [],
      args: [],
      memoryBus: {},
      executeLogs: [],
      userInput: {},
      allUserInputs: [],
      executionSteps: [],
      errorMessage: '', // 用于存储错误消息
      execution_count: 0,
      isRun: false,
      inputDialogVisible: false,
      showErrorLog: false, // 控制错误日志的显示/隐藏
      /* 上传文件相关 */
      fileList: [],
      file: null,
      fileData: null,
      formData: null,
      img: null,
      downloadLink: null,
      fileName: null,
      displayedResultsNum: [],
      // 用于跳转，存储每一步的各个变量
      allData: [],
      displayNowOnTask: 0,
      waitingTaskList: false, // 是否在等待调用工具完成
      avatarIndex: 0, // 控制用户头像
      chartLogHistory: [], // echart{id,option} 记录
      executeNum: 1  // 修改echart id
    }
  },
  computed: {
    notRunToEnd() {
      return this.nowOnTask < this.appDetail.task_list.length
    },
    runButtonMessage() {
      return (this.notRunToEnd ? '执行' : '重新执行')
    },
    executionCompleted() {
      return this.appDetail.task_list && this.nowOnTask >= this.appDetail.task_list.length
    }
  },
  created() {
    this.avatarIndex = parseInt(this.$store.getters.avatar) + 1
    this.appId = this.$route.query.id
    this.getDetailAndShow()
  },
  methods: {
    hasInputParam(userInput) {
      // 遍历userInput数组
      for (let argIndex = 0; argIndex < userInput.length; argIndex++) {
        const arg = userInput[argIndex]
        // 检查source属性是否等于'input'
        if (arg.source === 'input') {
          // 如果找到source为'input'的项，可以在这里执行相关操作
          // 例如，打印出来或者返回true表示找到了
          console.log(arg)
          return true
        }
      }
      // 如果遍历结束都没有找到source为'input'的项，返回false
      return false
    },
    getDetailAndShow() {
      if (this.chartLogHistory.length !== 0) {
        // 先找到old-history容器
        var historyContainer = document.getElementById('old-history')
        // const chart = historyContainer.querySelectorAll(`#${this.chartLogHistory[0].id}`);

        // 获取最上方启动信息框的宽度，让显示图表的宽度与之一致
        const startAppDialog = document.querySelector('#start-app-dialog')
        const width = startAppDialog.getBoundingClientRect().width

        // 循环遍历chartLogHistory数组
        this.chartLogHistory.forEach((logEntry) => {
          // 根据id找到对应的DOM元素
          const chartDom = historyContainer.querySelector(`#${logEntry.id}`)

          if (chartDom) {
            // 移除_echarts_instance_属性
            chartDom.removeAttribute('_echarts_instance_')
            // 让chart所在的标签有宽高可以被渲染
            chartDom.style.display = 'block'
            chartDom.style.width = width + 'px'
            // 渲染成功后，先将图表容器隐藏
            chartDom.style.display = 'none'
            const myChart = echarts.init(chartDom)
            // 设置图表的option
            myChart.setOption(logEntry.option, true)
            // 让chart所在的标签有宽高可以被渲染
            chartDom.style.display = 'block'
          } else {
            console.error(`Chart container with id ${logEntry.id} not found`)
          }
        })
      }
      this.executeNum += 1
      getAppDetail(this.appId, this.$store.getters.id).then(res => {
        console.log('获取到的应用详情:', res)
        this.appDetail = res
        this.appName = res.app_name
        // 获取图片ID
        this.imageId = this.getImageId(this.appName)
        this.autoFillArgs(this.execution_count)
      }).catch(error => {
        console.log('执行时获取详情出错:', error)
      })
    },
    getImageId(appName) {
      if (!appName || appName.length === 0) return 0
      const firstChar = appName[0].toUpperCase() // 取应用名称的首字母并转为大写
      const charCode = firstChar.charCodeAt(0) // 转换为字符编码
      return charCode % 20 // 对20取模，得到0-19
    },
    // 获取图片URL
    getImageUrl() {
      return require(`@/assets/icons/${this.imageId}.png`)
    },
    async autoFillArgs(task) {
      // 判断是否是第一次执行到这里，如果是，就把跳转相关的执行参数保存下来
      if (this.allData[task] === undefined) {
        this.allData[task] = {
          appDetail: JSON.parse(JSON.stringify(this.appDetail)),
          allUserInputs: JSON.parse(JSON.stringify(this.allUserInputs)),
          executionSteps: JSON.parse(JSON.stringify(this.executionSteps)),
          displayNowOnTask: JSON.parse(JSON.stringify(this.displayNowOnTask)),
          displayedResultsNum: JSON.parse(JSON.stringify(this.displayedResultsNum))
        }
      }

      this.nowOnTask = task
      this.nowTaskContent = this.appDetail.task_list.at(task)
      this.nowTaskArgs = []
      this.args = this.nowTaskContent.parameters

      await getExecutroMemoryBus().then((res) => {
        this.memoryBus = res
      }).catch(error => {
        console.log('子组件填参', error)
      })

      this.args.forEach(arg => {
        // 使多选框默认不选中
        if (arg.input && arg.input.options && !this.isSingleChoice(arg.input.options)) {
          arg.value = [] // Initialize to empty array for multi-choice inputs
        }
        // 使input输入框的profile能够正确识别
        if (arg.input && !arg.input.options) {
          // 如果该值为profile.开头，则默认其为使用profile中的变量；如果没取到对应变量，则不进行改变
          try {
            if (arg.value.startsWith('profile')) {
              const keys = arg.value.split('.')
              let current = this.memoryBus
              for (const key of keys) {
                current = current[key]
              }
              arg.value = current
            }
          } catch (e) {
            console.log(e)
          }
        }
      })

      const hasInputArgs = this.args.some(arg => arg.source === 'input') || this.args.some(arg => arg.source === 'file')
      const step = {
        userInput: this.args,
        task_id: this.execution_count + 1,
        tool_name: this.nowTaskContent.tool_name,
        canceled: false
      }
      this.executionSteps.push(step)

      if (hasInputArgs) {
        this.inputDialogVisible = true
      } else {
        this.submitForm()
      }
      this.$nextTick(() => {
        this.scrollToInput()
      })
    },
    hasInputArgs(step) {
      if (step.userInput.some(arg => arg.source === 'input') || step.userInput.some(arg => arg.source === 'file')) {
        this.waitingTaskList = false
      }
      return step.userInput.some(arg => arg.source === 'input') || step.userInput.some(arg => arg.source === 'file')
    },
    isSingleChoice(options) {
      return options.some(option => option.hasOwnProperty('checked'))
    },
    changeHandler(file, fileList) {
      this.fileList = fileList
      if (file) {
        const reader = new FileReader()
        reader.onload = (e) => {
          // 获取文件内容
          this.fileData = e.target.result
          // 可以在此处处理文件内容，例如预览图片或显示文本
          console.log('文件内容：', e.target.result)
        }
        reader.onerror = (e) => {
          // 处理读取文件时的错误
          console.error('读取文件时发生错误：', e)
        }

        // console.log('1111', file)
        // console.log('2222', this.fileData)
        // 根据文件类型决定读取方式
        if (file.type.startsWith('image/')) {
          // 如果是图片，可以直接将file.raw的URL赋值给图片预览的src属性
          // this.fileData = URL.createObjectURL(file.raw)
          this.fileData = reader.readAsDataURL(file)
        } else {
          // 如果是文本文件，以文本的方式读取
          this.fileData = reader.readAsText(file.raw)
        }
      } else {
        console.error('文件未找到')
      }
    },
    async submitForm() {
      try {
        // const currentFile = this.fileList[this.fileList.length - 1]
        // this.changeHandler(this.file, this.fileList)
        // console.log('11111：', this.fileData)

        if (this.fileList) {
          // console.log('55555555555555')
          this.appDetail.file = this.fileData
        }

        const res = await getExecutroMemoryBus()
        this.memoryBus = res
        this.args.forEach(arg => {
          if (arg.source === 'refer') {
            const path = arg.value.split('.')
            let value = this.memoryBus
            for (let i = 0; i < path.length; i++) {
              value = value[path[i]]
              if (value === undefined) break
            }
            arg.value = value
          }
        })

        const dataToSend = this.nowTaskContent.parameters.reduce((acc, arg) => {
          acc[arg.name] = arg.value
          return acc
        }, {})
        Object.keys(dataToSend).forEach(key => {
          const arg = this.args.find(arg => arg.name === key)
          if (arg) {
            arg.value = dataToSend[key]
          }
        })
        // existing submitForm logic
        const userInput = this.args.reduce((acc, arg) => {
          if (arg.source === 'input') {
            if (arg.input.options) {
              if (this.isSingleChoice(arg.input.options)) {
                // Single choice logic
                const selectedOption = arg.input.options.find(option => option.value === arg.value)
                acc[arg.name] = selectedOption ? selectedOption.name : arg.value
              } else {
                // Multi-choice logic
                const selectedOptions = arg.input.options.filter(option => arg.value.includes(option.value))
                acc[arg.name] = selectedOptions.map(option => option.name).join(';')
              }
            } else {
              acc[arg.name] = arg.value
            }
          } else if (arg.source === 'const') {
            acc[arg.name] = {
              value: arg.value,
              type: 'Const'
            }
          } else if (arg.source === 'refer') {
            acc[arg.name] = {
              value: arg.value,
              type: 'Refer'
            }
          }
          if (arg.source === 'file') {
            arg.value = this.fileName
            // console.log('3333', arg.value)
          }
          return acc
        }, {})

        userInput.tool_name = this.nowTaskContent.tool_name
        const argsWithoutInput = this.args.map(arg => {
          const { input, ...rest } = arg
          if (typeof input !== 'undefined') {
            rest['userDefinedName'] = input['name']
          }
          return rest
        })
        this.userInput = userInput
        this.allUserInputs.push(userInput) // Store user inputs for display

        // Update the appDetail args without input
        this.appDetail.task_list.at(this.nowOnTask).parameters = argsWithoutInput

        console.log(this.waitingTaskList)
        this.displayNowOnTask += 1
        if (!this.waitingTaskList) {
          this.waitingTaskList = true
        }
        // Process next step
        executeAppStep({ 'appDetail': this.appDetail, 'id': this.$store.getters.id }).then(response => {
          console.log('单步执行task：', response)
          this.executeLogs.push(response)
          // console.log('executeLogs', this.executeLogs[0])
          // if (this.appDetail.file) {
          //   // console.log('进入下载文件中：')
          //   // 调用 downloadFile 函数
          //   downloadFile().then(data => {
          //     console.log('文件下载成功:', data)
          //     this.createImageFromBinaryStream(data)
          //   }).catch(error => {
          //     console.error('文件下载失败:', error)
          //   })
          // }
          this.nowOnTask += 1
          if (this.waitingTaskList) {
            // this.waitingTaskList = false
          }
          // console.log('NOWTask：', this.nowOnTask)
          this.showChart()

          // Update the prompt field in the step object
          this.executionSteps[this.nowOnTask - 1].prompt = this.args.find(arg => arg.source === 'input')?.input.prompt || ''

          if (this.notRunToEnd) {
            this.autoFillArgs(this.nowOnTask)
          } else {
            // 所有任务已完成，滚动到页面底部
            this.scrollToCompletion()
          }
        }).catch(error => {
          if (!error.response.data.message) {
            this.errorMessage = '未知错误'
          } else {
            // 胶水代码用户中止执行，就会执行if, 跳转就会执行else if
            if (error.response.data.message === 'error to execute: Aborting the current program') {
              this.$message.warning('The user has aborted the current program')
              this.errorMessage = 'The user has aborted the current program'
            } else if (error.response.data.message.startsWith('error to execute: Error in user function: Skip to step ')) {
              // 获取用户要跳转的步骤
              const step = parseInt(error.response.data.message.slice(55))
              // 根据要跳转的步骤改变前端的样式
              this.appDetail = JSON.parse(JSON.stringify(this.allData[step - 1].appDetail))
              this.allUserInputs = JSON.parse(JSON.stringify(this.allData[step - 1].allUserInputs))
              this.executionSteps = JSON.parse(JSON.stringify(this.allData[step - 1].executionSteps))
              this.displayNowOnTask = JSON.parse(JSON.stringify(this.allData[step - 1].displayNowOnTask))
              this.displayedResultsNum = JSON.parse(JSON.stringify(this.allData[step - 1].displayedResultsNum))
              this.execution_count = step - 1
              this.autoFillArgs(step - 1)
            } else if (error.response.data.message.startsWith('error to execute: Error in user function: Skip back to step ')) {
              // 获取用户要向后跳转的步骤
              const step = parseInt(error.response.data.message.slice(60))
              // 根据要跳转的步骤改变前端的样式
              // 将跳过的步骤添加到executionSteps/allUserInputs/executeLogs中
              for (let i = 0; i < step - 2 - this.nowOnTask; i++) {
                // 加入executionSteps中
                const step = {
                  userInput: this.appDetail.task_list.at(this.nowOnTask + i + 1).parameters,
                  task_id: this.nowOnTask + i + 1,
                  tool_name: this.appDetail.task_list.at(this.nowOnTask + i + 1).tool_name,
                  canceled: false
                }
                this.executionSteps.push(step)
                // 加入allUserInputs中
                const a = {}
                for (const i of step.userInput) {
                  i.source = 'input'
                  a[i.name] = '跳过'
                }
                this.allUserInputs.push(a)
                // 这是根据每一步是否返回结果来加载输出的
                this.executeLogs.push('')
                this.displayedResultsNum.push(0)
              }
              // 跳转前那一步没加入进来，所以要多加一步
              this.executeLogs.push('')
              this.displayedResultsNum.push(0)
              this.execution_count = step - 1

              this.displayNowOnTask = step - 1
              this.autoFillArgs(step - 1)
            } else {
              this.errorMessage = error.response.data.message
            }
          }
          console.log('执行单步task失败：', error.response.data)
        })
        this.execution_count += 1
      } catch (error) {
        console.log('获取MemoryBus失败:', error)
      }

      this.$nextTick(() => {
        this.scrollToInput()
      })
    },

    createImageFromBinaryStream(base64String) {
      // 将Base64字符串解码为二进制数据
      const binaryStream = atob(base64String) // atob() 用于解码Base64字符串
      const len = binaryStream.length
      const bytes = new Uint8Array(len)
      for (let i = 0; i < len; i++) {
        bytes[i] = binaryStream.charCodeAt(i)
      }
      // 将二进制流转换为Blob对象
      const blob = new Blob([bytes], { type: 'image/png' }) // 根据实际图片类型设置MIME类型

      // 创建一个临时URL
      const imageUrl = URL.createObjectURL(blob)

      // 创建img元素
      self.img = document.createElement('img')
      self.img.src = imageUrl

      // 设置最大宽度和最大高度
      self.img.style.maxWidth = '100%'
      self.img.style.maxHeight = '500px'

      // 设置object-fit属性
      self.img.style.objectFit = 'contain'

      // 设置height属性
      self.img.style.height = 'auto'

      // 将img元素添加到特定的div中
      // const imageContainer = document.getElementById('image_load')
      // imageContainer.appendChild(self.img)

      // 创建下载链接
      self.downloadLink = document.createElement('a')
      self.downloadLink.href = imageUrl
      self.downloadLink.download = 'downloaded_image.png' // 指定下载的文件名
      self.downloadLink.textContent = '下载'

      // 将下载链接添加到DOM中
      // imageContainer.appendChild(self.downloadLink)

      // 在不需要时释放URL对象
      // URL.revokeObjectURL(imageUrl);
    },

    cancelExecution(index) {
      this.executionSteps[index].canceled = true
    },
    showChart() {
      this.$nextTick(() => {
        // 先找到new-history容器
        const historyContainer = document.getElementById('new-history')
        // 确保找到了new-history容器

        const chartDom = historyContainer.querySelector(`#chart-${this.nowOnTask - 1}`)
        const textContainer = historyContainer.querySelector(`#text-${this.nowOnTask - 1}`)
        const fileContainer = historyContainer.querySelector(`#file-${this.nowOnTask - 1}`)

        if (!chartDom) {
          console.error(`DOM element with ID "chart-${this.nowOnTask - 1}" not found.`)
          return
        }
        // 让chart所在的标签有宽高可以被渲染
        chartDom.style.display = 'block'
        // 获取最上方启动信息框的宽度，让显示图表的宽度与之一致
        const startAppDialog = document.querySelector('#start-app-dialog')
        const width = startAppDialog.getBoundingClientRect().width
        chartDom.style.width = width + 'px'
        const myChart = echarts.init(chartDom)
        // 渲染成功后，先将图表容器隐藏
        chartDom.style.display = 'none'
        textContainer.style.display = 'none'
        fileContainer.style.display = 'none'

        getExecutroMemoryBus().then(res => {
          console.log('res:', res)
          const results = res.yf_processed_output.result
          const taskNum = this.nowOnTask - 1 // 当前任务编号
          console.log('results: ', results)
          this.displayedResultsNum.push(0)
          if (results && results.length > 0) {
            this.memoryBusData[taskNum] = results
            this.memoryBusData[taskNum].forEach(item => {
              if (item.type === 'echart' && item.option) {
                this.chartLogHistory.push({ id: 'chart-' + this.executeNum + '-' + taskNum, option: item.option })
                // 如果是图表类型，设置图表的配置
                this.waitingTaskList = false
                this.displayedResultsNum[taskNum] = 1
                myChart.setOption(item.option)
                chartDom.style.display = 'block' // 显示图表
                var sourceEchartContainer = document.getElementById('chart-' + taskNum)
                sourceEchartContainer.id = 'chart-' + this.executeNum + '-' + taskNum
              } else if (item.type === 'text' && item.data) {
                // 如果是文本类型，展示文本内容
                this.waitingTaskList = false
                this.displayedResultsNum[taskNum] = 1
                if (textContainer) {
                  textContainer.innerHTML = item.data // 设置文本内容
                  textContainer.style.display = 'block' // 显示文本
                }
              } else if (item.type === 'file') {
                this.displayedResultsNum[taskNum] = 1
                this.createImageFromBinaryStream(item.data)
                this.waitingTaskList = false
                if (fileContainer) {
                  fileContainer.style.display = 'block' // 显示文件
                  fileContainer.appendChild(self.img) // 显示图片
                  var spaceNode = document.createElement('span')
                  spaceNode.innerHTML = '&nbsp;&nbsp;'
                  fileContainer.appendChild(spaceNode)
                  fileContainer.style.whiteSpace = 'normal'
                  fileContainer.appendChild(self.downloadLink) // 显示链接
                }
              }
            })
            this.scrollToCompletion()
            // console.log('getExecutroMemoryBus结果：', res.yf_processed_output.result.option);
            // myChart.setOption(res.yf_processed_output.result.option);
            // chartDom.style.display = 'block';  // 显示图表
          } else {
            console.warn('No chart option available.')
            chartDom.style.display = 'none' // 隐藏图表
            textContainer.style.display = 'none' // 隐藏文本
            fileContainer.style.display = 'none' // 隐藏文件
          }
        }).catch(error => {
          console.log('processOutput出错:', error)
          chartDom.style.display = 'none' // 隐藏图表
          textContainer.style.display = 'none' // 隐藏文本
          fileContainer.style.display = 'none' // 隐藏文件
        })
      })
    },

    getOringalImg() {
      return URL.createObjectURL(this.file)
    },
    downloadUrl() {
      return URL.createObjectURL(this.file)
    },
    showOriginalFile() {
      const fileContainer = document.getElementById('uploadOriginalFile')

      if (fileContainer) {
        // 清空容器中可能存在的旧内容
        fileContainer.innerHTML = ''

        // 创建img元素
        const img = document.createElement('img')
        img.src = URL.createObjectURL(this.file) // 使用文件对象创建URL
        img.alt = 'Uploaded Image'
        img.style.maxWidth = '100%' // 根据需要调整样式

        // 创建下载链接
        const downloadLink = document.createElement('a')
        downloadLink.href = URL.createObjectURL(this.file)
        downloadLink.download = this.file.name // 使用文件的实际名称
        downloadLink.textContent = '下载'
        downloadLink.style.display = 'inline-block'
        downloadLink.style.margin = '0 10px' // 根据需要调整样式

        // 将img元素和下载链接添加到容器中
        fileContainer.appendChild(img)
        fileContainer.appendChild(downloadLink)
      }
    },

    scrollToCompletion() {
      this.$nextTick(() => {
        const target = this.$refs.completionMessage

        if (target) {
          const targetPosition = target.getBoundingClientRect().top + window.scrollY
          window.scrollTo({
            top: targetPosition,
            behavior: 'smooth' // 平滑滚动
          })
        } else {
          console.error('Target element not found')
        }
      })
    },
    scrollToInput() {
      this.$nextTick(() => {
        // Ensure that DOM updates have completed before trying to scroll
        const formItem = this.$el.querySelector('.el-form-item:last-of-type')
        if (formItem) {
          const top = formItem.getBoundingClientRect().top + window.scrollY
          window.scrollTo({
            top,
            behavior: 'smooth' // Smooth scrolling
          })
        } else {
          console.error('Form item not found')
        }
      })
    },
    toggleErrorLog() {
      this.showErrorLog = !this.showErrorLog // 切换错误日志显示状态
    },
    restartExecution() {
      // 获取ID为'new-history'的元素
      var sourceContainer = document.getElementById('new-history')

      // 获取ID为're-start'的元素
      var reStartDiv = document.querySelectorAll('#re-start')

      // 检查是否找到了reStartDiv
      if (reStartDiv) {
        // 设置display属性为none，隐藏该元素
        for (let i = 0; i < reStartDiv.length; i++) {
          reStartDiv[i].style.display = 'none'
        }
      } else {
        console.error('无法找到ID为re-start的元素')
      }
      // 检查是否找到了sourceContainer
      if (sourceContainer) {
        // 获取ID为'old-history'的容器元素
        var targetContainer = document.getElementById('old-history')

        // 检查是否找到了targetContainer
        if (targetContainer) {
          // 复制sourceContainer下的所有子元素
          var children = Array.from(sourceContainer.children)

          // 将每个子元素添加到targetContainer中
          children.forEach(function(child) {
            // 添加到targetContainer
            targetContainer.appendChild(child.cloneNode(true))
          })
        } else {
          console.error('无法找到ID为old-history的容器元素')
        }
      } else {
        console.error('无法找到ID为new-history的容器元素')
      }

      this.memoryBusData = {} // 用来存储不同 taskNum 对应的 memoryBus 数据
      this.imageId = 0
      this.appDetail = {}
      this.appName = ''
      this.nowOnTask = 0
      this.nowTaskContent = {}
      this.nowTaskArgs = []
      this.args = []
      this.memoryBus = {}
      this.executeLogs = []
      this.userInput = {}
      this.allUserInputs = []
      this.executionSteps = []
      this.errorMessage = ''
      this.execution_count = 0
      this.isRun = false
      this.inputDialogVisible = false
      this.showErrorLog = false
      this.fileList = []
      this.file = null
      this.fileData = null
      this.formData = null
      this.img = null
      this.downloadLink = null
      this.fileName = null
      this.displayedResultsNum = []
      this.allData = []
      this.displayNowOnTask = 0
      this.waitingTaskList = false // 是否在等待调用工具完成
      this.getDetailAndShow() // 重新获取应用详情并初始化
    },

    // 上传文件的请求发送函数
    uploadFile(param) {
      this.file = param.file
      this.formData = new FormData()
      // 获取文件名称
      this.fileName = param.file.name
      this.formData.append('file', param.file)
      uploadFile(this.formData).then(response => {
        console.log('上传文件成功', response)
        // 保存二进制格式的文件
        this.fileData = response
        this.$emit('save-file', response)
        // 文件图标设为绿色
        param.onSuccess()
      }).catch(error => {
        console.log('上传文件失败', error)
        // param.onError()
      })
    },
    // 移除上传文件的处理函数
    beforeRemoveFile(file, fileList) {
      return this.$confirm(`${this.$t('sure_remove_tip')}${file.name}?`)
    },
    // 上传文件个数超过限制的处理函数
    handleExceed(files, fileList) {
      this.$message.warning(`${this.$t('file_upload_tip_one')}，${this.$t('file_upload_tip_two')} ${files.length} ${this.$t('file_upload_tip_four')}，${this.$t('file_upload_tip_three')} ${files.length + fileList.length} ${this.$t('file_upload_tip_four')}`)
    }
  }
}
</script>

<style scoped>
.dialog-box {
  border-radius: 10px;
}

.responsive-image {
  max-width: 100%;
  /* 最大宽度为100%，即容器的宽度 */
  max-height: 500px;
  /* 假设最大高度为500px */
  object-fit: contain;
  /* 等比例缩放图片以适应容器 */
  height: auto;
  /* 高度自动调整 */
}

.execute {
  width: 70%;
}

.logs {
  width: 30%;
}

.buttons {
  margin-top: 20px;
}

.center {
  margin: 0 auto;
  display: block;
}

.user {
  flex-direction: row;
}

.yuanfang {
  flex-direction: row-reverse;
}

.user-icon {
  position: absolute;
  right: 0;
  top: 0;
  margin: 10px;
  /* 根据需要调整 */
}

.content-wrapper {
  background-color: white;
  padding: 15px;

  /* 确保输入框不会被图片覆盖，可以根据图片的宽度进行调整 */
}

.user-avatar {
  cursor: pointer;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  margin-bottom: 5px;
}

.yuanfang-avatar {
  cursor: pointer;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  margin-bottom: 10px;
}

.button-container {
  display: flex;
  justify-content: center;
  margin-top: 10px;
}

.waiting-task-list{
  padding-top: 15px;
  padding-bottom: 15px;
  padding-left: 10px;
  background-color: white;
}

.sub-task {
  margin-bottom: 15px;
}
</style>
